'''
Created on 23/12/2009

@author: vinicius
'''
from funcoes import euclidiana, valorMinimo
from padrao import Padrao
from numpy import var

class KMeans():
    
    def __init__(self,numClusters,treinamento):
        self.treinamento = treinamento
        self.clusters = [None]*numClusters
        self.centroides  = []
        self.varClusters = [None]*numClusters
    
    def executar(self):
        self.initClusters()
        self.computeGrupos()
        parada = False
        while (parada):
            self.computeCentroides()
            self.computeGrupos()
            self.computeVariancia()
            parada = self.computeCriterioParada()
    
    def getCentroides(self):
        listarCentroides = []
        for cluster in self.clusters:
            listarCentroides.append(cluster.centroide)
        return listarCentroides
    
    def initClusters(self):
        for i in len(range(self.clusters)):
            centroideInicial = self.treinamento[i]
            self.clusters.append(centroideInicial)
            self.clusters[i].centroide = centroideInicial
            self.treinamento.pop(i)
            
    def computeGrupos(self):
        listClusters = [None]*len(self.clusters)
        for padrao in self.treinamento:
            distanciasPadraoGrupo = []
            for cluster in self.clusters:
                distanciasPadraoGrupo.append(euclidiana(padrao,cluster.centroide))
            indice = valorMinimo(distanciasPadraoGrupo)
            listClusters[indice] = padrao
        for indice in range(len(listClusters)):
            self.clusters[indice].padroes = listClusters[indice].padroes
            
    def computeCentroides(self):
        media =0.0
        atributos = []
        for k in range(len(self.clusters)):
            cluster = self.clusters[k]
            for i in range(len(cluster.centroide.atributos)):
                for padrao in cluster.padroes:
                    media += padrao.atributos[i]
                media /= len(cluster)
                atributos.append(media)
            novoCentroide = Padrao()
            novoCentroide.atributos = atributos
            cluster.centroide = novoCentroide
            self.centroides[k] = novoCentroide
        
    def computeCriterioParada(self):
        parada = False
        for i in range(len(self.clusters)):
            centroideCalculado = self.clusters[i].centroide
            centroideAtual = self.centroides[i].centroide
            if centroideAtual == centroideCalculado:
                parada = True
            else:
                parada = False
                break
        return parada
    
    def computeVariancia(self):
        valoresVariavel = []
        for i in range(len(self.treinamento[0].atributos)):
            for k in range(len(self.clusters)):
                cluster = self.clusters[k]
                varAtributo = []
                for padrao in cluster.padroes:
                    valoresVariavel.append(padrao.atributos[i])
                desvio = var(valoresVariavel)
                varAtributo[i] = desvio
            self.varClusters[k] = varAtributo

class Cluster():
    def __init__(self):
        self.padroes = []
        self.centroide = None